package com.hcl.orm.core.dialect.handler.func;

import cn.hutool.core.util.StrUtil;
import com.hcl.orm.core.annotation.DBType;
import com.hcl.orm.core.dialect.SqlDefinition;
import com.hcl.orm.core.dialect.handler.AbstractDialectHandler;
import com.hcl.orm.core.exception.NotSupportFunctionException;
import com.hcl.orm.core.exception.OrmException;

import java.util.ArrayList;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * @author hucl
 * @projectName hcl-orm
 * @description: 函数翻译基类
 * @date 2021/8/1114:16
 */
public abstract class FuncDialectHandler extends AbstractDialectHandler {
    /**
     * 标准函数--字符串拼接函数
     */
    protected static final String FUNC_HS_CONCAT = "hs_concat";
    /**
     * 标准函数--判断第一个参数为空赋予默认值
     */
    protected static final String FUNC_HS_NVL = "hs_nvl";
    /**
     * 日期累加
     */
    protected static final String FUNC_HS_ADD_DAY = "hs_add_day";
    /**
     * 月份累加
     */
    protected static final String FUNC_HS_ADD_MONTH = "hs_add_month";
    /**
     * 日期差值
     */
    protected static final String FUNC_HS_DATEDIFF = "hs_datediff";
    /**
     * 时间格式化
     */
    protected static final String FUNC_HS_TIME_FORMAT = "hs_time_format";
    /**
     * 时间戳函数
     */
    protected static final String FUNC_HS_TIMESTAMP_INT = "hs_timestamp_int";
    /**
     * 四舍五入
     */
    protected static final String FUNC_HS_CEIL = "hs_ceil";
    /**
     * 日期格式
     */
    protected static final String FUNC_HS_DATE_FORMAT = "hs_date_format";
    /**
     * 取当天日期整型
     */
    protected static final String FUNC_HS_DATE_INT = "hs_date_int";
    protected static final String FUNC_HS_ROWNUM = "hs_rownum";
    protected static final String FUNC_HS_SYSDATE = "hs_sysdate";
    /**
     * 日期时间整型格式
     */
    protected static final String FUNC_HS_DATETIME_INT = "hs_datetime_int";
    /**
     * 通用函数
     */
    protected static final String FUNC_HS_CHAR = "hs_char";
    protected static final String FUNC_HS_ASCII = "hs_ascii";
    protected static final String FUNC_HS_FLOOR = "hs_floor";
    protected static final String FUNC_HS_LENGTH = "hs_length";
    protected static final String FUNC_HS_LPAD = "hs_lpad";
    protected static final String FUNC_HS_LOWER = "hs_lower";
    protected static final String FUNC_HS_UPPER = "hs_upper";
    protected static final String FUNC_HS_REPLACE = "hs_replace";
    protected static final String FUNC_HS_ROUND = "hs_round";
    protected static final String FUNC_HS_TRIMB = "hs_trimb";
    protected static final String FUNC_HS_ABS = "hs_abs";
    protected static final String FUNC_HS_MAX = "hs_max";
    protected static final String FUNC_HS_MIN = "hs_min";
    protected static final String FUNC_HS_NUMBER = "hs_number";
    protected static final String FUNC_HS_SUBSTR = "hs_substr";
    protected static final String FUNC_HS_GROUP_CONCAT = "hs_group_concat";
    protected static final String FUNC_HS_TIMESTAMPDIFF = "hs_timestampdiff";
    protected static final String FUNC_HS_TO_DATE = "hs_to_date";
    /**
     * 获取函数字符串的正则表达式
     */
    private static final Pattern FUN_PATTERN = Pattern.compile("(hs_\\.?[\\w]+)\\(");

    public FuncDialectHandler(String name) {
        super(name);
    }

    @Override
    protected boolean needHandled(SqlDefinition sqlDefinition) {
        return StrUtil.isNotEmpty(sqlDefinition.getRawSql()) &&
                sqlDefinition.getSelectedSqlMetadata()
                        .getTargetType().equals(DBType.ALL);
    }

    /**
     * 从原始HSSQL中提取所有标准函数
     *
     * @param hsSqlTmpl
     * @return
     */
    protected List<String> extractFuncStr(String hsSqlTmpl) {
        List<String> ret = new ArrayList<>();
        Matcher matcher = FUN_PATTERN.matcher(hsSqlTmpl);
        while (matcher.find()) {
            int count = 1;
            for (int i = matcher.end(); i < hsSqlTmpl.length(); i++) {
                char value = hsSqlTmpl.charAt(i);
                if (value == '(') {
                    count++;
                } else if (value == ')') {
                    count--;
                    if (count == 0) {
                        ret.add(hsSqlTmpl.substring(matcher.start(), i + 1));
                        break;
                    }
                } else {
                    continue;
                }
            }
        }
        return ret;
    }

    /**
     * 从函数字符串中提取函数名
     *
     * @param funcStr
     * @return
     */
    protected String extractFuncName(String funcStr) {
        return StrUtil.subBefore(funcStr, '(', false);
    }

    /**
     * 从函数字符串中提取参数
     *
     * @param funcStr
     * @return
     */
    protected List<String> extractFuncInputs(String funcStr) {
        List<String> ret = new ArrayList<>();
        String inputStr = StrUtil.subBefore(StrUtil.subAfter(funcStr, '(', false), ')',
                true);
        int nestCount = 0;
        int startIndex = 0;
        for (int i = 0; i < inputStr.length(); i++) {
            if (inputStr.charAt(i) == '(') {
                nestCount++;
            } else if (inputStr.charAt(i) == ')') {
                nestCount--;
            }
            if (nestCount == 0) {
                if (inputStr.charAt(i) == ',') {
                    ret.add(inputStr.substring(startIndex, i));
                    startIndex = i + 1;
                } else if (i == inputStr.length() - 1) {
                    ret.add(inputStr.substring(startIndex, i + 1));
                    startIndex = i + 1;
                }
            }
            continue;
        }
        return ret;
    }


    public String replaceCommonFunc(String funcName) {
        switch (funcName) {
            case FUNC_HS_CHAR:
                return "char";
            case FUNC_HS_ASCII:
                return "ascii";
            case FUNC_HS_FLOOR:
                return "floor";
            case FUNC_HS_LENGTH:
                return "length";
            case FUNC_HS_LPAD:
                return "lpad";
            case FUNC_HS_LOWER:
                return "lower";
            case FUNC_HS_REPLACE:
                return "replace";
            case FUNC_HS_ROUND:
                return "round";
            case FUNC_HS_UPPER:
                return "upper";
            case FUNC_HS_TRIMB:
                return "trim";
            case FUNC_HS_CONCAT:
                return "concat";
            case FUNC_HS_NVL:
                return "ifnull";
            case FUNC_HS_DATEDIFF:
                return "datediff";
            case FUNC_HS_ABS:
                return "abs";
            case FUNC_HS_CEIL:
                return "ceil";
            case FUNC_HS_GROUP_CONCAT:
                return "group_concat";
            case FUNC_HS_MAX:
                return "max";
            case FUNC_HS_MIN:
                return "min";
            case FUNC_HS_NUMBER:
                return "hs_number";
            case FUNC_HS_SUBSTR:
                return "substring";
            case FUNC_HS_TIMESTAMPDIFF:
                return "timestampdiff";
            case FUNC_HS_SYSDATE:
                return "now";
            default:
                throw new NotSupportFunctionException(funcName + " is not support.");
        }

    }
}
